from math import pi, sin, cos, asin, acos, atan, atan2, sqrt, copysign
from pyglet.gl import *

from awesum import Terrain, Vector3, Quaternion, degToRad, radToDeg
from part import TrackPart

class ArenaTrackPart(TrackPart):
	def getExits(self):
		"""The arena pieces fill up their entire 3d rect with exits"""
		#TODO there should probably be a more efficient way to do this,
		#	but then again, getExits isn't a standard, it's only for the
		#	track game so far, so maybe I shouldn't care. Shrug. It is in
		#	the Load call after all.
		exits = []
		for x in range(self.loc.x, self.loc.x + self.size.x):
			for y in range(self.loc.y, self.loc.y + self.size.y):
				for z in range(self.loc.z, self.loc.z + self.size.z):
					exits.append(Vector3(x, y, z))
		return exits

class EdgeTF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeTF, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeTF, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		numSeg = 20 #depth #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r
			ang2 = unitAng * r2
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(left, sin(ang1) * radius + self.baseHeight, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(right, sin(ang1) * radius + self.baseHeight, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(right, sin(ang2) * radius + self.baseHeight, cos(ang2) * radius - radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(left, sin(ang2) * radius + self.baseHeight, cos(ang2) * radius - radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeXAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, pt.y - self.yMin, pt.z - self.zMin), -1)

class EdgeTB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeTB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeTB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		numSeg = 20 #depth #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + deg90
			ang2 = unitAng * r2 + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(left, sin(ang1) * radius + self.baseHeight, cos(ang1) * radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(right, sin(ang1) * radius + self.baseHeight, cos(ang1) * radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(right, sin(ang2) * radius + self.baseHeight, cos(ang2) * radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(left, sin(ang2) * radius + self.baseHeight, cos(ang2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeXAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, pt.y - self.yMin, self.zMax - pt.z), -1)

class EdgeTL(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeTL, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeTL, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = abs(self.size.x * block.x)
		radius = width
		numSeg = 20 #width #self.size.x * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		back = 0.
		front = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0., self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi + deg90
			ang2 = unitAng * r2 + pi + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius + radius, cos(ang1) * radius + self.baseHeight, back)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius + radius, cos(ang1) * radius + self.baseHeight, front)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius + radius, cos(ang2) * radius + self.baseHeight, front)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius + radius, cos(ang2) * radius + self.baseHeight, back)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeZAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, pt.y - self.yMin, 0.), -1)

class EdgeTR(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeTR, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeTR, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = abs(self.size.x * block.x)
		radius = width
		numSeg = 20 #width #self.size.x * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		back = 0.
		front = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0., self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r
			ang2 = unitAng * r2
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius, cos(ang1) * radius + self.baseHeight, front)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius, cos(ang1) * radius + self.baseHeight, back)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius, cos(ang2) * radius + self.baseHeight, back)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius, cos(ang2) * radius + self.baseHeight, front)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeZAxisGetNextPoint(self, d, Vector3(pt.x - self.xMin, pt.y - self.yMin, 0.), -1)

class EdgeBF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeBF, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeBF, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		numSeg = 20 #depth #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi + deg90
			ang2 = unitAng * r2 + pi + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(left, sin(ang1) * radius + self.baseHeight + radius, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(right, sin(ang1) * radius + self.baseHeight + radius, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(right, sin(ang2) * radius + self.baseHeight + radius, cos(ang2) * radius - radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(left, sin(ang2) * radius + self.baseHeight + radius, cos(ang2) * radius - radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeXAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, self.yMax - pt.y, pt.z - self.zMin))

class EdgeBB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeBB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeBB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		deg90 = pi / 2.
		numSeg = 20 #depth #self.size.z * 5
		unitAng = deg90 / numSeg
		
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi
			ang2 = unitAng * r2 + pi
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(left, sin(ang1) * radius + self.baseHeight + radius, cos(ang1) * radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(right, sin(ang1) * radius + self.baseHeight + radius, cos(ang1) * radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(right, sin(ang2) * radius + self.baseHeight + radius, cos(ang2) * radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(left, sin(ang2) * radius + self.baseHeight + radius, cos(ang2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeXAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, self.yMax - pt.y, self.zMax - pt.z))

class EdgeBL(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeBL, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeBL, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = abs(self.size.x * block.x)
		radius = width
		numSeg = 20 #width #self.size.x * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		back = 0.
		front = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0., self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi
			ang2 = unitAng * r2 + pi
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius + radius, cos(ang1) * radius + self.baseHeight + radius, back)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius + radius, cos(ang1) * radius + self.baseHeight + radius, front)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius + radius, cos(ang2) * radius + self.baseHeight + radius, front)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius + radius, cos(ang2) * radius + self.baseHeight + radius, back)
			
		glEnd()
		glEndList()

	def getNextPoint(self, d):
		pt = d.origin
		return _edgeZAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, self.yMax - pt.y, 0.))

class EdgeBR(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeBR, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeBR, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = abs(self.size.x * block.x)
		radius = width
		numSeg = 20 #width #self.size.x * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		back = 0.
		front = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0., self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + deg90
			ang2 = unitAng * r2 + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius, cos(ang1) * radius + self.baseHeight + radius, back)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius, cos(ang1) * radius + self.baseHeight + radius, front)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius, cos(ang2) * radius + self.baseHeight + radius, front)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius, cos(ang2) * radius + self.baseHeight + radius, back)
			
		glEnd()
		glEndList()

	def getNextPoint(self, d):
		pt = d.origin
		return _edgeZAxisGetNextPoint(self, d, Vector3(pt.x - self.xMin, self.yMax - pt.y, 0.))

class EdgeLF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeLF, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeLF, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = radius = abs(self.size.x * block.x)
		numSeg = 20 #width #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		bottom = self.baseHeight
		top = self.size.y * block.y + self.baseHeight

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi + deg90
			ang2 = unitAng * r2 + pi + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius + radius, bottom,cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius + radius, top, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius + radius, top, cos(ang2) * radius - radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius + radius, bottom, cos(ang2) * radius - radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeYAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, 0., self.zMin - pt.z))

class EdgeLB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeLB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeLB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = radius = abs(self.size.x * block.x)
		numSeg = 20 #width #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		bottom = self.baseHeight
		top = self.size.y * block.y + self.baseHeight

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + pi
			ang2 = unitAng * r2 + pi
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius + radius, bottom,cos(ang1) * radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius + radius, top, cos(ang1) * radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius + radius, top, cos(ang2) * radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius + radius, bottom, cos(ang2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeYAxisGetNextPoint(self, d, Vector3(self.xMax - pt.x, 0., self.zMax - pt.z), -1)

class EdgeRF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeRF, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeRF, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = radius = abs(self.size.x * block.x)
		numSeg = 20 #width #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		bottom = self.baseHeight
		top = self.size.y * block.y + self.baseHeight

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r
			ang2 = unitAng * r2
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius, bottom,cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius, top, cos(ang1) * radius - radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius, top, cos(ang2) * radius - radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius, bottom, cos(ang2) * radius - radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeYAxisGetNextPoint(self, d, Vector3(pt.x - self.xMin, 0., self.zMin - pt.z))

class EdgeRB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(EdgeRB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(EdgeRB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		width = radius = abs(self.size.x * block.x)
		numSeg = 20 #width #self.size.z * 5
		deg90 = pi / 2.
		unitAng = deg90 / numSeg
		
		bottom = self.baseHeight
		top = self.size.y * block.y + self.baseHeight

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, numSeg):
			r2 = r + 1
			ang1 = unitAng * r + deg90
			ang2 = unitAng * r2 + deg90
			
			yTex1 = float(r)/(numSeg-1)
			yTex2 = float(r2)/(numSeg-1)
			
			glTexCoord2f(0, yTex1)
			glVertex3f(sin(ang1) * radius, bottom,cos(ang1) * radius)
			glTexCoord2f(1, yTex1)
			glVertex3f(sin(ang1) * radius, top, cos(ang1) * radius)
			glTexCoord2f(1, yTex2)
			glVertex3f(sin(ang2) * radius, top, cos(ang2) * radius)
			glTexCoord2f(0, yTex2)
			glVertex3f(sin(ang2) * radius, bottom, cos(ang2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _edgeYAxisGetNextPoint(self, d, Vector3(pt.x - self.xMin, 0., self.zMax - pt.z), -1)

class CornerTLF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerTLF, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(self.xMax - pt.x, pt.y - self.yMin, pt.z - self.zMin))

class CornerTLB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerTLB, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(self.xMax - pt.x, pt.y - self.yMin, self.zMax - pt.z))

class CornerTRF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerTRF, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(pt.x - self.xMin, pt.y - self.yMin, pt.z - self.zMin))

class CornerTRB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerTRB, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(pt.x - self.xMin, pt.y - self.yMin, self.zMax - pt.z))

class CornerBLF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerBLF, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(self.xMax - pt.x, self.yMax - pt.y, pt.z - self.zMin))

class CornerBLB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerBLB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(CornerBLB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		stepAmt = 1
		left = 0
		right = self.size.x * block.x
		bottom = self.yMin
		top = self.yMax

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, depth / 2):
			r2 = r + stepAmt
			xzAng = (r / (depth / 2.)) * (pi / 2.) + 180. * degToRad
			xzAng2 = (r2 / (depth / 2.)) * (pi / 2.) + 180. * degToRad
			glTexCoord2f(0, 0)
			glVertex3f(sin(xzAng) * radius + radius, top, cos(xzAng) * radius)
			glTexCoord2f(1, 0)
			glVertex3f(sin(xzAng) * radius + radius, bottom, cos(xzAng) * radius)
			glTexCoord2f(1, 1)
			glVertex3f(sin(xzAng2) * radius + radius, bottom, cos(xzAng2) * radius)
			glTexCoord2f(0, 1)
			glVertex3f(sin(xzAng2) * radius + radius, top, cos(xzAng2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(self.xMax - pt.x, self.yMax - pt.y, self.zMax - pt.z))

class CornerBRF(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerBRF, self).__init__(loc, size, coeff, eq)
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(pt.x - self.xMin, self.yMax - pt.y, pt.z - self.zMin))

class CornerBRB(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(CornerBRB, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(CornerBRB, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = abs(self.size.z * block.z)
		radius = depth
		stepAmt = 1
		left = 0
		right = self.size.x * block.x
		bottom = self.yMin
		top = self.yMax

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0., self.loc.z * block.z)
		glBegin(GL_QUADS)
		for r in range(0, depth / 2):
			r2 = r + stepAmt
			xzAng = (r / (depth / 2.)) * (pi / 2.) + 90. * degToRad
			xzAng2 = (r2 / (depth / 2.)) * (pi / 2.) + 90. * degToRad
			glTexCoord2f(0, 0)
			glVertex3f(sin(xzAng) * radius, top, cos(xzAng) * radius)
			glTexCoord2f(1, 0)
			glVertex3f(sin(xzAng) * radius, bottom, cos(xzAng) * radius)
			glTexCoord2f(1, 1)
			glVertex3f(sin(xzAng2) * radius, bottom, cos(xzAng2) * radius)
			glTexCoord2f(0, 1)
			glVertex3f(sin(xzAng2) * radius, top, cos(xzAng2) * radius)
			
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin
		return _cornerGetNextPoint(self, d, Vector3(pt.x - self.xMin, self.yMax - pt.y, self.zMax - pt.z))

class SurfaceTop(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceTop, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceTop, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = self.size.z * block.z
		height = self.baseHeight + self.size.y * block.y
		radius = depth
		stepAmt = 1
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		#for r in range(0, depth):
			#r2 = r + stepAmt
		glTexCoord2f(0, 0)
		glVertex3f(right, height, 0)
		glTexCoord2f(1, 0)
		glVertex3f(left, height, 0)
		glTexCoord2f(1, 1)
		glVertex3f(left, height, depth)
		glTexCoord2f(0, 1)
		glVertex3f(right, height, depth)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.y = self.yMax
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(-asin(v.y / 100.), 0., asin(v2.y / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		return pt

class SurfaceBottom(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceBottom, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceBottom, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		depth = self.size.z * block.z
		radius = depth
		stepAmt = 1
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		#for r in range(0, depth):
			#r2 = r + stepAmt
		glTexCoord2f(0, 0)
		glVertex3f(left, self.baseHeight, 0)
		glTexCoord2f(1, 0)
		glVertex3f(right, self.baseHeight, 0)
		glTexCoord2f(1, 1)
		glVertex3f(right, self.baseHeight, depth)
		glTexCoord2f(0, 1)
		glVertex3f(left, self.baseHeight, depth)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.y = self.yMin
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(asin(v.y / 100.), 0., -asin(v2.y / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		return pt

class SurfaceFront(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceFront, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceFront, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		height = self.size.y * block.y
		front = 0
		stepAmt = 1
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		glTexCoord2f(0, 0)
		glVertex3f(right, self.baseHeight, front)
		glTexCoord2f(1, 0)
		glVertex3f(left, self.baseHeight, front)
		glTexCoord2f(1, 1)
		glVertex3f(left, self.baseHeight + height, front)
		glTexCoord2f(0, 1)
		glVertex3f(right, self.baseHeight + height, front)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.z = self.zMax
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(-asin(v.z / 100.), 0., asin(v2.z / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		return pt

class SurfaceBack(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceBack, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceBack, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		height = self.size.y * block.y
		depth = self.size.z * block.z
		stepAmt = 1
		left = 0
		right = self.size.x * block.x

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		glTexCoord2f(0, 0)
		glVertex3f(left, self.baseHeight, depth)
		glTexCoord2f(1, 0)
		glVertex3f(right, self.baseHeight, depth)
		glTexCoord2f(1, 1)
		glVertex3f(right, self.baseHeight + height, depth)
		glTexCoord2f(0, 1)
		glVertex3f(left, self.baseHeight + height, depth)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.z = self.zMin
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(asin(v.z / 100.), 0., -asin(v2.z / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		return pt

class SurfaceLeft(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceLeft, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceLeft, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		height = self.size.y * block.y
		left = 0
		stepAmt = 1
		front = 0
		back = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		glTexCoord2f(0, 0)
		glVertex3f(left, self.baseHeight, front)
		glTexCoord2f(1, 0)
		glVertex3f(left, self.baseHeight, back)
		glTexCoord2f(1, 1)
		glVertex3f(left, self.baseHeight + height, back)
		glTexCoord2f(0, 1)
		glVertex3f(left, self.baseHeight + height, front)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.x = self.xMin
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(asin(v.x / 100.), 0., -asin(v2.x / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		return pt

class SurfaceRight(ArenaTrackPart):
	def __init__(self, loc, size, coeff=1, eq=0):
		super(SurfaceRight, self).__init__(loc, size, coeff, eq)
	
	def load(self, game=None):
		super(SurfaceRight, self).load(game)
		
		block = self.game["BLOCK_SIZE"]
		height = self.size.y * block.y
		right = self.size.x * block.x
		stepAmt = 1
		front = 0
		back = self.size.z * block.z

		glNewList(self.gl.id, GL_COMPILE)
		glTranslatef(self.loc.x * block.x, 0, self.loc.z * block.z)
		glBegin(GL_QUADS)
		glTexCoord2f(0, 0)
		glVertex3f(right, self.baseHeight, back)
		glTexCoord2f(1, 0)
		glVertex3f(right, self.baseHeight, front)
		glTexCoord2f(1, 1)
		glVertex3f(right, self.baseHeight + height, front)
		glTexCoord2f(0, 1)
		glVertex3f(right, self.baseHeight + height, back)
		glEnd()
		glEndList()
	
	def getNextPoint(self, d):
		pt = d.origin.copy()
		speed = d.move.speed
		
		if self.firstStep:
			pt.x = self.xMax
			v = d.move.quat.rotateV(Vector3(0., 0., 100.))
			v2 = d.move.quat.rotateV(Vector3(100., 0., 0.))
			q = Quaternion().setEuler(Vector3(-asin(v.x / 100.), 0., asin(v2.x / 100.)))
			d.move.quat *= q #Flatten local X and Z rotation
		
		change = d.moved = d.move.quat.rotateV(Vector3(0., 0., speed))
		pt += change
		
		return pt

#Helper functions for similar type track parts

def _edgeXAxisGetNextPoint(tp, d, distIn, sign=1):
	radius = tp.size.y * tp.game["BLOCK_SIZE"].y
	speed = d.move.speed
	
	pt = d.origin.copy()
	#find the car's current radius relative to the tp X origin axis
	carPosRadius = sqrt(distIn.y**2 + distIn.z**2)
	#find the difference in radii to correct it in the relative movement
	radiusDiff = carPosRadius - radius
	
	vAdd = d.moved = d.move.quat.rotateV(Vector3(0., radiusDiff, speed))
	pt += vAdd
	
	#angle of change in X rotation =
	#	arc (the distance in speed across the Z and Y axis) /
	#	radius of the TP
	#	and make it positive or negative depending on the quadrant
	angChange = copysign(sqrt(vAdd.z**2 + vAdd.y**2) / radius, -vAdd.z * sign)
	
	q = Quaternion().setEuler(Vector3(angChange, 0., 0.))
	d.move.quat = q * d.move.quat
	
	return pt

def _edgeYAxisGetNextPoint(tp, d, distIn, sign=1):
	radius = tp.size.x * tp.game["BLOCK_SIZE"].x
	speed = d.move.speed
	
	pt = d.origin.copy()
	#find the car's current radius relative to the tp Y origin axis
	carPosRadius = sqrt(distIn.x**2 + distIn.z**2)
	#find the difference in radii to correct it in the relative movement
	radiusDiff = carPosRadius - radius
	
	vAdd = d.moved = d.move.quat.rotateV(Vector3(0., radiusDiff, speed))
	pt += vAdd
	
	#angle of change in Y rotation =
	#	arc (the distance in speed across the Z and X axis) /
	#	radius of the TP
	#	and make it positive or negative depending on the quadrant
	angChange = copysign(sqrt(vAdd.z**2 + vAdd.x**2) / radius, vAdd.x * sign)
	
	q = Quaternion().setEuler(Vector3(0., angChange, 0.))
	d.move.quat = q * d.move.quat
	
	return pt

def _edgeZAxisGetNextPoint(tp, d, distIn, sign=1):
	radius = tp.size.x * tp.game["BLOCK_SIZE"].x
	speed = d.move.speed
	
	pt = d.origin.copy()
	#find the car's current radius relative to the tp Z origin axis
	carPosRadius = sqrt(distIn.x**2 + distIn.y**2)
	#find the difference in radii to correct it in the relative movement
	radiusDiff = carPosRadius - radius
	
	vAdd = d.moved = d.move.quat.rotateV(Vector3(0., radiusDiff, speed))
	pt += vAdd
	
	#angle of change in Z rotation =
	#	arc (the distance in speed across the X and Y axis) /
	#	radius of the TP
	#	and make it positive or negative depending on the quadrant
	angChange = copysign(sqrt(vAdd.x**2 + vAdd.y**2) / radius, vAdd.x * sign)
	
	q = Quaternion().setEuler(Vector3(0., 0., angChange))
	d.move.quat = q * d.move.quat
	
	return pt

def _cornerGetNextPoint(tp, d, distIn):
	"""Move the car around the inside of a sphere
	tp = current track piece
	d = the drawable object passing through
	distIn = distance inside of the tp WRT the sphere origin
	"""
	radius = tp.size.x * tp.game["BLOCK_SIZE"].x
	speed = d.move.speed
	
	#find the car's current radius relative to the tp X origin axis
	carPosRadius = sqrt(distIn.x**2 + distIn.y**2 + distIn.z**2)
	#find the difference in radii to correct it in the relative movement
	radiusDiff = carPosRadius - radius
	
	#Position in front of the car, slightly up the slope
	yUp = radius - (cos(speed / radius) * radius)
	
	#Local rotation on the X axis to lift the front of the car
	d.move.quat *= Quaternion().setEuler(Vector3(-speed/radius, 0., 0.))
	
	#Rotate the car's forward movement vector, and add it to its location
	change = d.moved = d.move.quat.rotateV(Vector3(0., yUp + radiusDiff, speed))
	return d.origin + change